﻿#include "Renderer.h"
#include <spdlog/spdlog.h>	
#include <SDL2/SDL_render.h>

engine::render::Renderer::Renderer(SDL_Renderer* sdlRenderer, engine::resource::ResourceManager* resourceManager):
	m_sdlRenderer(sdlRenderer), m_resourceManager(resourceManager)
{
	if (!m_sdlRenderer)
	{
		spdlog::error("SDL_Renderer 初始化失败: {}", SDL_GetError());
		throw std::runtime_error("SDL_Renderer 初始化失败");
	}
	if (!m_resourceManager)
	{
		spdlog::error("ResourceManager 未初始化");
		throw std::runtime_error("ResourceManager 未初始化");
	}
	setDrawColor(0, 0, 0, 255); //默认黑色
	spdlog::info("Renderer 初始化成功");	
}

void engine::render::Renderer::drawSprite(const Camera& camera, const Sprite& sprite, const glm::vec2& position, const glm::vec2& scale, double angle)
{
	const std::string& textureID = sprite.getTextureID(); 
	SDL_Texture* texture = m_resourceManager->getTexture(textureID); 
	if (!texture) 
	{
		spdlog::error("Texture 获取失败: {}", textureID); 
		return; 
	} 
	std::optional<SDL_FRect> srcRect = getSpriteSrcRect(sprite); 

	if (!srcRect.has_value())
	{
		spdlog::error("无法获取 Sprite 的源矩形: {}", textureID); 
		return; 
	}
	 glm::vec2 position_screen = camera.worldToScreen(position);

	 float scaled_w = srcRect.value().w * scale.x; 
	 float scaled_h = srcRect.value().h * scale.y; 
	 SDL_FRect dstRect = { position_screen.x, position_screen.y, scaled_w, scaled_h };
	 if (!isRectInViewport(camera, dstRect))
	 {
		 return;
	 } //不在视口内，跳过绘制 
	 
	 SDL_Rect srcRectInt;
	 srcRectInt.x = static_cast<int>(srcRect->x);
	 srcRectInt.y = static_cast<int>(srcRect->y);
	 srcRectInt.w = static_cast<int>(srcRect->w);
	 srcRectInt.h = static_cast<int>(srcRect->h);

	 SDL_FRect dstRectInt;
	 dstRectInt.x = dstRect.x;
	 dstRectInt.y = dstRect.y;
	 dstRectInt.w = dstRect.w;
	 dstRectInt.h = dstRect.h;

	 SDL_FPoint center = { static_cast<int>(dstRect.w / 2), static_cast<int>(dstRect.h / 2) };

	 if (SDL_RenderCopyExF(m_sdlRenderer, texture, &srcRectInt, &dstRect, angle, &center, SDL_FLIP_NONE) != 0)
	 {
		 spdlog::error("渲染 Sprite 失败: {}", SDL_GetError());
	 }

}

void engine::render::Renderer::drawParallax(const Camera& camera, const Sprite& sprite, const glm::vec2& position, glm::vec2& scroll_factor, const glm::bvec2& repeat, const glm::vec2& scale)
{
	const std::string& textureID = sprite.getTextureID();
	SDL_Texture* texture = m_resourceManager->getTexture(textureID);
	if (!texture)
	{
		spdlog::error("Texture 获取失败: {}", textureID);
		return;
	}

	std::optional<SDL_FRect> srcRect = getSpriteSrcRect(sprite);
	if (!srcRect.has_value())
	{
		spdlog::error("无法获取 Sprite 的源矩形: {}", textureID);
		return;
	}

	glm::vec2 position_screen = camera.worldToScreenwithParallax(position, scroll_factor);
	float scaled_w = srcRect->w * scale.x;
	float scaled_h = srcRect->h * scale.y;

	glm::vec2 viewportSize = camera.getViewportSize();
	glm::vec2 start, stop;

	// X方向
	if (repeat.x)
	{
		start.x = glm::mod(position_screen.x, scaled_w) - scaled_w;
		stop.x = viewportSize.x;
	}
	else
	{
		start.x = position_screen.x;
		stop.x = glm::min(position_screen.x + scaled_w, viewportSize.x);
	}

	// Y方向
	if (repeat.y)
	{
		start.y = glm::mod(position_screen.y, scaled_h) - scaled_h;
		stop.y = viewportSize.y;
	}
	else
	{
		start.y = position_screen.y;
		stop.y = glm::min(position_screen.y + scaled_h, viewportSize.y);
	}

	SDL_Rect srcRectInt = {
		static_cast<int>(srcRect->x),
		static_cast<int>(srcRect->y),
		static_cast<int>(srcRect->w),
		static_cast<int>(srcRect->h)
	};

	for (float y = start.y; y < stop.y; y += scaled_h)
	{
		for (float x = start.x; x < stop.x; x += scaled_w)
		{
			SDL_FRect dstRect = { x, y, scaled_w, scaled_h };
			if (SDL_RenderCopyF(m_sdlRenderer, texture, &srcRectInt, &dstRect) != 0)
			{
				spdlog::error("渲染 Parallax Sprite 失败: {}", SDL_GetError());
				return;
			}
		}
	}
}

void engine::render::Renderer::drawUISprite(const Sprite& sprite, const glm::vec2& position, const std::optional<glm::vec2>& size)
{
	const std::string& textureID = sprite.getTextureID();
	SDL_Texture* texture = m_resourceManager->getTexture(textureID);
	if (!texture)
	{
		spdlog::error("Texture 获取失败: {}", textureID);
		return;
	}

	std::optional<SDL_FRect> srcRect = getSpriteSrcRect(sprite);
	if (!srcRect.has_value())
	{
		spdlog::error("无法获取 Sprite 的源矩形: {}", textureID);
		return;
	}

	SDL_FRect dstRect = { position.x, position.y, 0, 0 };
	if (size.has_value())
	{
		dstRect.w = size->x;
		dstRect.h = size->y;
	}
	else
	{
		dstRect.w = srcRect->w;
		dstRect.h = srcRect->h;
	}

	SDL_Rect srcRectInt = 
	{
		static_cast<int>(srcRect->x),
		static_cast<int>(srcRect->y),
		static_cast<int>(srcRect->w),
		static_cast<int>(srcRect->h)
	};

	if (SDL_RenderCopyF(m_sdlRenderer, texture, &srcRectInt, &dstRect) != 0)
	{
		spdlog::error("渲染 UI Sprite 失败: {}", SDL_GetError());
	}
}

void engine::render::Renderer::present()
{
	SDL_RenderPresent(m_sdlRenderer);
}

void engine::render::Renderer::clearScreen()
{
	if (SDL_RenderClear(m_sdlRenderer) != 0)
	{
		spdlog::error("清除屏幕失败: {}", SDL_GetError());
	}
}

inline void engine::render::Renderer::setDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
	if (!SDL_SetRenderDrawColor(m_sdlRenderer, r, g, b, a))
	{
		spdlog::error("设置绘制颜色失败: {}", SDL_GetError());
	}
}

inline void engine::render::Renderer::setDrawColorFloat(float r, float g, float b, float a)
{
	Uint8 R = static_cast<Uint8>(r * 255.0f);
	Uint8 G = static_cast<Uint8>(g * 255.0f);
	Uint8 B = static_cast<Uint8>(b * 255.0f);
	Uint8 A = static_cast<Uint8>(a * 255.0f);

	SDL_SetRenderDrawColor(m_sdlRenderer, R, G, B, A);
}

inline SDL_Renderer* engine::render::Renderer::getSDLRenderer() const
{
	return m_sdlRenderer;
}

std::optional<SDL_FRect> engine::render::Renderer::getSpriteSrcRect(const Sprite& sprite)
{
	 const std::string& textureID = sprite.getTextureID();
	 SDL_Texture* texture = m_resourceManager->getTexture(textureID);
	 if (!texture)
	 {
		 spdlog::error("Texture 获取失败: {}", textureID);
		 return std::nullopt;
	 }
	 const std::optional<SDL_Rect>& srcRect = sprite.getSrcRect();
	 if (srcRect.has_value())
	 {
		 if (srcRect.value().x <= 0 || srcRect.value().y <= 0)
		 {
			 spdlog::error("Sprite 源矩形无效: {}", textureID);
			 return std::nullopt;
		 }
	 }
	 else
	 {
		 SDL_FRect result = {0,0,0,0};
		 int w, h;
		 if (SDL_QueryTexture(texture, nullptr, nullptr, &w, &h) == 0)
		 {
			 result.w = static_cast<float>(w);
			 result.h = static_cast<float>(h);
			 return result;
		 }
		 else
		 {
			 spdlog::error("无法查询纹理尺寸: {}", textureID);
			 return std::nullopt;
		 }
	 }
}

bool engine::render::Renderer::isRectInViewport(const Camera& camera, const SDL_FRect& rect)
{
	glm::vec2 viewportSize = camera.getViewportSize();

	bool overlapX = rect.x + rect.w > 0 && rect.x < viewportSize.x;
	bool overlapY = rect.y + rect.h > 0 && rect.y < viewportSize.y;

	return overlapX && overlapY;
}
